import Foundation
import UIKit

private enum PresententionStyle {
    case rect (CGRect)
    case barButton (UIBarButtonItem)
}

private let alertDelegate = AlertDelegate()
private var clickedButtonAtIndexBlock:((Int) -> Void)?

class AlertDelegate : NSObject, UIAlertViewDelegate, UIActionSheetDelegate {
    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
        clickedButtonAtIndexBlock!(buttonIndex)
    }
  
    func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int) {
        if UIDevice.current.userInterfaceIdiom == .pad {
            clickedButtonAtIndexBlock!(buttonIndex + 1)
        } else {
            clickedButtonAtIndexBlock!(buttonIndex)
        }
    }
}

class MTAlert : NSObject {
    fileprivate class func topViewController () -> UIViewController {
        let rootViewController = UIApplication.shared.keyWindow?.rootViewController
        assert(rootViewController != nil, "App has no keyWindow, cannot present Alert/Action Sheet.")
        let navVC = rootViewController as! UINavigationController
        return navVC.topViewController ?? rootViewController!
    }
    
    fileprivate class func topVisibleViewController(_ viewController: UIViewController) -> UIViewController {
        if viewController is UITabBarController {
            return MTAlert.topVisibleViewController((viewController as! UITabBarController).selectedViewController!)
        } else if viewController is UINavigationController {
            return MTAlert.topVisibleViewController((viewController as! UINavigationController).visibleViewController!)
        } else if viewController.presentedViewController != nil {
            return MTAlert.topVisibleViewController(viewController.presentedViewController!)
        } else if viewController.children.count > 0 {
            return MTAlert.topVisibleViewController(viewController.children.last!)
        }
        return viewController
    }
  
    class func presentActionSheet(title: String?,
        cancelButtonTitle: String,
        destructiveButtonTitle: String?,
        otherButtonTitles: [String],
        barButtonItem:UIBarButtonItem,
        clickedButtonAtIndex:((_ buttonIndex:Int) -> ())? = nil) {
            
            self.presentActionSheet(title,
                cancelButtonTitle: cancelButtonTitle,
                destructiveButtonTitle: destructiveButtonTitle,
                otherButtonTitles: otherButtonTitles,
                presententionStyle: .barButton(barButtonItem),
                clickedButtonAtIndex: clickedButtonAtIndex)
    }
    
    class func presentActionSheet(title: String?,
        cancelButtonTitle: String,
        destructiveButtonTitle:String?,
        otherButtonTitles: [String],
        frame:CGRect,
        clickedButtonAtIndex:((_ buttonIndex:Int) -> ())? = nil) {
            
            self.presentActionSheet(title,
                cancelButtonTitle: cancelButtonTitle,
                destructiveButtonTitle: destructiveButtonTitle,
                otherButtonTitles: otherButtonTitles,
                presententionStyle: .rect(frame),
                clickedButtonAtIndex: clickedButtonAtIndex)
    }
    
    fileprivate class func presentActionSheet(_ title: String?,
        cancelButtonTitle: String,
        destructiveButtonTitle:String?,
        otherButtonTitles: [String],
        presententionStyle:PresententionStyle,
        clickedButtonAtIndex:((_ buttonIndex:Int) -> ())? = nil) {
            
            let currentViewController = MTAlert.topViewController()
            
            if kSystemVersion > 8.0 {
                var buttonOffset = 1
                let alert = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)

              
                alert.addAction(UIAlertAction(title: cancelButtonTitle, style: .cancel, handler:
                    {(alert: UIAlertAction) in
                        if let _clickedButtonAtIndex = clickedButtonAtIndex {
                            _clickedButtonAtIndex(0)
                        }
                }))
                
                if let _destructiveButtonTitle = destructiveButtonTitle {
                    alert.addAction(UIAlertAction(title: _destructiveButtonTitle, style: .destructive, handler:
                        {(alert: UIAlertAction) in
                            if let _clickedButtonAtIndex = clickedButtonAtIndex {
                                _clickedButtonAtIndex(1)
                            }
                    }))
                    buttonOffset += 1
                }
                
                for (index, string) in otherButtonTitles.enumerated() {
                    alert.addAction(UIAlertAction(title: string, style: .default, handler:
                        {(alert: UIAlertAction) in
                            if let _clickedButtonAtIndex = clickedButtonAtIndex {
                                _clickedButtonAtIndex(index + buttonOffset)
                            }
                    }))
                }
                
                if UIDevice.current.userInterfaceIdiom == .pad {
                    alert.popoverPresentationController?.sourceView = currentViewController.view
                    switch presententionStyle {
                    case let .rect(rect):
                        alert.popoverPresentationController?.sourceRect = rect
                    default:
                        alert.popoverPresentationController?.sourceRect = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: 100)
                    }
                }
                
                currentViewController.present(alert, animated: true, completion: nil)
                
            } else {
                let alert = UIActionSheet()
                
                if let _title = title {
                    alert.title = _title
                }
                
                if UIDevice.current.userInterfaceIdiom == .phone {
                    alert.cancelButtonIndex = 0
                    alert.addButton(withTitle: cancelButtonTitle)
                }
                
                if let _destructiveButtonTitle = destructiveButtonTitle {
                    alert.destructiveButtonIndex = UIDevice.current.userInterfaceIdiom == .phone ? 1 : 0
                    alert.addButton(withTitle: _destructiveButtonTitle)
                }
                
                for string in otherButtonTitles {
                    alert.addButton(withTitle: string)
                }
                
                if let _clickedButtonAtIndex = clickedButtonAtIndex {
                    clickedButtonAtIndexBlock = _clickedButtonAtIndex
                    alert.delegate = alertDelegate
                }
                
                if UIDevice.current.userInterfaceIdiom == .phone {
                    alert.show(in: currentViewController.view)
                } else {
                    switch presententionStyle {
                    case let .rect(rect):
                        alert.show(from: rect, in: currentViewController.view, animated: true)
                    case let .barButton(barButton):
                        alert.show(from: barButton, animated: true)
                    }
                }
            }
    }
    
    class func presentAlert(title: String,
        message: String,
        cancelButtonTitle: String,
        otherButtonTitles: [String]? = nil,
        needDestructiveIndex : Int = -1,
        clickedButtonAtIndex:((_ buttonIndex:Int) -> ())? = nil) {
            
            if kSystemVersion > 8.0 {
                let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
                
                alert.addAction(UIAlertAction(title: cancelButtonTitle, style: .cancel, handler:
                    {(alert: UIAlertAction) in
                        if let _clickedButtonAtIndex = clickedButtonAtIndex {
                            _clickedButtonAtIndex(0)
                        }
                }))
                
                if let _otherButtonTitles = otherButtonTitles {
                    for (index, string) in _otherButtonTitles.enumerated() {
                        if needDestructiveIndex >= 0 && index == needDestructiveIndex{
                            alert.addAction(UIAlertAction(title: string, style: .destructive, handler:
                                {(alert: UIAlertAction) in
                                    if let _clickedButtonAtIndex = clickedButtonAtIndex {
                                        _clickedButtonAtIndex(index + 1)
                                    }
                            }))
                        }else{
                            alert.addAction(UIAlertAction(title: string, style: .default, handler:
                                {(alert: UIAlertAction) in
                                    if let _clickedButtonAtIndex = clickedButtonAtIndex {
                                        _clickedButtonAtIndex(index + 1)
                                    }
                            }))
                        }
                    }
                }
                
                let currentViewController = MTAlert.topViewController()
                currentViewController.present(alert, animated: true, completion: nil)
            } else {
                let alert = UIAlertView()
                alert.addButton(withTitle: cancelButtonTitle);
                alert.cancelButtonIndex = 0
                alert.title = title
                alert.message = message
                
                if let _otherButtonTitles = otherButtonTitles {
                    for string in _otherButtonTitles {
                        alert.addButton(withTitle: string)
                    }
                }
                
                if let _clickedButtonAtIndex = clickedButtonAtIndex {
                    clickedButtonAtIndexBlock = _clickedButtonAtIndex
                    alert.delegate = alertDelegate
                }
                
                alert.show()
            }
    }
}
